parameters:
  steps: []                       # optional -- any additional steps that need to happen before pulling down the performance repo and sending the performance benchmarks to helix (ie building your repo)
  variables: []                   # optional -- list of additional variables to send to the template
  jobName: ''                     # required -- job name
  displayName: ''                 # optional -- display name for the job. Will use jobName if not passed
  pool: ''                        # required -- name of the Build pool
  container: ''                   # required -- name of the container
  buildConfig: ''                 # required -- build configuration
  archType: ''                    # required -- targeting CPU architecture
  osGroup: ''                     # required -- operating system for the job
  osSubgroup: ''                  # optional -- operating system subgroup
  extraSetupParameters: ''        # optional -- extra arguments to pass to the setup script
  frameworks: ['netcoreapp3.0']   # optional -- list of frameworks to run against
  continueOnError: 'false'        # optional -- determines whether to continue the build if the step errors
  dependsOn: ''                   # optional -- dependencies of the job
  timeoutInMinutes: 320           # optional -- timeout for the job
  enableTelemetry: false          # optional -- enable for telemetry
  liveLibrariesBuildConfig: ''    # optional -- live-live libraries configuration to use for the run
  pgoRunType: ''                  # optional -- different PGO configurations
  physicalPromotionRunType: ''    # optional -- different physical promotion configurations
  r2rRunType: ''                  # optional -- different R2R configurations
  experimentName: ''              # optional -- name of the experiment
  runtimeType: 'coreclr'          # optional -- Sets the runtime as coreclr or mono
  codeGenType: 'JIT'              # optional -- Decides on the codegen technology if running on mono
  projectFile: 'microbenchmarks.proj'   # optional -- project file to build helix workitems
  runKind: ''                     # required -- test category
  logicalMachine: ''              # required -- Used to specify a which pool of machines the test should run against
  javascriptEngine: 'NoJS'
  helixTypeSuffix: ''             # optional -- appends to HelixType
  collectHelixLogsScript: ''      # optional -- script to collect the logs, and artifacts helpful for debugging failures
  additionalSetupParameters: ''   # optional -- additional setup parameters that are job-specific

jobs:
- template: /eng/pipelines/common/templates/runtimes/xplat-job.yml
  parameters:
    dependsOn: ${{ parameters.dependsOn }}
    buildConfig: ${{ parameters.buildConfig }}
    archType: ${{ parameters.archType }}
    osGroup: ${{ parameters.osGroup }}
    osSubgroup: ${{ parameters.osSubgroup }}
    liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }}
    enableTelemetry: ${{ parameters.enableTelemetry }}
    enablePublishBuildArtifacts: true
    continueOnError: ${{ parameters.continueOnError }}

    ${{ if ne(parameters.displayName, '') }}:
      displayName: '${{ parameters.displayName }}'
    ${{ if eq(parameters.displayName, '') }}:
      displayName: '${{ parameters.jobName }}'
    name: ${{ replace(replace(parameters.jobName, ' ', '_'), '-', '_') }}

    timeoutInMinutes: ${{ parameters.timeoutInMinutes }}

    variables:
    - ${{ each variable in parameters.variables }}:
      - ${{insert}}: ${{ variable }}

    - IsInternal: ''
    - HelixApiAccessToken: ''
    - ${{ if and(eq(parameters.runtimeType, 'wasm'), in(variables['Build.Reason'], 'PullRequest')) }}:
      - HelixPerfUploadTokenValue: ''
    - ${{ if and(notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.osGroup, 'windows')) }}:
      - HelixPerfUploadTokenValue: '$(PerfCommandUploadTokenLinux)'
    - ${{ if and(notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.osGroup, 'windows')) }}:
      - HelixPerfUploadTokenValue: '$(PerfCommandUploadToken)'
    - ${{ if eq(parameters.runtimeType, 'wasm') }}:
      # nodejs installation steps from https://github.com/nodesource/distributions
      - HelixPreCommandsWasmOnLinux: >-
          export RestoreAdditionalProjectSources=$HELIX_CORRELATION_PAYLOAD/built-nugets &&
          sudo apt-get -y remove nodejs &&
          sudo apt-get update &&
          sudo apt-get install -y ca-certificates curl gnupg &&
          sudo mkdir -p /etc/apt/keyrings &&
          sudo rm -f /etc/apt/keyrings/nodesource.gpg &&
          curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor --batch -o /etc/apt/keyrings/nodesource.gpg &&
          export NODE_MAJOR=18 &&
          echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list &&
          sudo apt-get update &&
          sudo apt-get install nodejs -y &&
          test -n "$(V8Version)" &&
          npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g &&
          $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 v8@$(V8Version) &&
          export V8_ENGINE_PATH=~/.jsvu/bin/v8-$(V8Version) &&
          ${V8_ENGINE_PATH} -e 'console.log(`V8 version: ${this.version()}`)'
    - ${{ if ne(parameters.runtimeType, 'wasm') }}:
      - HelixPreCommandsWasmOnLinux: echo
    - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install urllib3==1.26.15;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(HelixPerfUploadTokenValue)"'
    - HelixPreCommandStemLinux: >-
        export ORIGPYPATH=$PYTHONPATH
        export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true;
        echo "** Installing prerequistes **";
        sudo apt-get -y install python3-pip &&
        python3 -m pip install --user -U pip &&
        sudo apt-get -y install python3-venv &&
        python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv &&
        ls -l $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate &&
        export PYTHONPATH= &&
        python3 -m pip install --user -U pip &&
        pip3 install urllib3==1.26.15 &&
        pip3 install --user azure.storage.blob==12.0.0 &&
        pip3 install --user azure.storage.queue==12.0.0 &&
        sudo apt-get update &&
        sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates &&
        $(HelixPreCommandsWasmOnLinux) &&
        export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"
        || export PERF_PREREQS_INSTALL_FAILED=1;
        test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **"
    - HelixPreCommandStemMusl: 'ulimit -n 4096;export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install urllib3==1.26.15;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"'
    - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"'
    - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"'
    - HelixPreCommand: ''
    - HelixPostCommand: ''
    - Interpreter: ''

    - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
      - ${{ if eq( parameters.osGroup, 'windows') }}:
        - HelixPreCommand: $(HelixPreCommandStemWindows);$(ExtraMSBuildLogsWindows)
        - HelixPostCommand: 'set PYTHONPATH=%ORIGPYPATH%'
        - IsInternal: -Internal
      - ${{ if ne(parameters.osGroup, 'windows') }}:
        - ${{ if eq(parameters.osSubGroup, '_musl') }}:
          - HelixPreCommand: $(HelixPreCommandStemMusl);$(ExtraMSBuildLogsLinux)
          - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH'
          - IsInternal: --internal
        - ${{ if ne(parameters.osSubGroup, '_musl') }}:
          - HelixPreCommand: $(HelixPreCommandStemLinux);$(ExtraMSBuildLogsLinux)
          - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH;${{ parameters.collectHelixLogsScript }}'
          - IsInternal: --internal
      - group: DotNet-HelixApi-Access
      - group: dotnet-benchview

    - ${{ if not(and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'))) }}:
      - ${{ if eq( parameters.osGroup, 'windows') }}:
        - HelixPreCommand: $(HelixPreCommandStemWindows);$(ExtraMSBuildLogsWindows)
        - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH;${{ parameters.collectHelixLogsScript }}'
      - ${{ if ne(parameters.osGroup, 'windows') }}:
        - HelixPreCommand: $(HelixPreCommandStemLinux);$(ExtraMSBuildLogsLinux);
        - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH;${{ parameters.collectHelixLogsScript }}'

    - ${{ if and(eq(parameters.codeGenType, 'Interpreter'), eq(parameters.runtimeType, 'mono')) }}:
      - ${{ if eq( parameters.osGroup, 'windows') }}:
        - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
          - HelixPreCommand: '$(HelixPreCommandStemWindows);set MONO_ENV_OPTIONS="--interpreter";$(ExtraMSBuildLogsWindows)'
          - Interpreter: ' -MonoInterpreter'
        - ${{ if not(and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'))) }}:
          - HelixPreCommand: 'set MONO_ENV_OPTIONS="--interpreter";$(ExtraMSBuildLogsWindows)'
          - Interpreter: ' -MonoInterpreter'
      - ${{ if ne(parameters.osGroup, 'windows') }}:
        - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
          - HelixPreCommand: '$(HelixPreCommandStemLinux);export MONO_ENV_OPTIONS="--interpreter";$(ExtraMSBuildLogsLinux)'
          - Interpreter: ' --monointerpreter'
        - ${{ if not(and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'))) }}:
          - HelixPreCommand: 'export MONO_ENV_OPTIONS="--interpreter";$(ExtraMSBuildLogsLinux)'
          - Interpreter: ' --monointerpreter'


    workspace:
      clean: all
    pool:
      ${{ parameters.pool }}
    ${{ if ne(parameters.runtimeType, 'wasm') }}:
      container: ${{ parameters.container }}
    strategy:
      matrix:
        ${{ each framework in parameters.frameworks }}:
          ${{ framework }}:
            _Framework: ${{ framework }}
    steps:
    - ${{ parameters.steps }}
    - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal)$(Interpreter) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.pgoRunType }} ${{ parameters.physicalPromotionRunType }} ${{ parameters.r2rRunType }} -ExperimentName '${{ parameters.experimentName }}' -UseLocalCommitTime ${{ parameters.extraSetupParameters }}
      displayName: Performance Setup (Windows)
      condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'))
      continueOnError: ${{ parameters.continueOnError }}
    - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal)$(Interpreter) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} ${{ parameters.pgoRunType }} ${{ parameters.physicalPromotionRunType }} ${{ parameters.r2rRunType }} --experimentname '${{ parameters.experimentName }}' --uselocalcommittime ${{ parameters.extraSetupParameters }}
      displayName: Performance Setup (Unix)
      condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'))
      continueOnError: ${{ parameters.continueOnError }}
    - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) ${{ parameters.additionalSetupParameters }}
      displayName: Run ci setup script
      # Run perf testing in helix
    - template: /eng/pipelines/coreclr/templates/perf-send-to-helix.yml
      parameters:
        HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/
        HelixType: 'test/performance/$(Kind)/$(_Framework)/$(Architecture)${{ parameters.helixTypeSuffix }}'
        HelixAccessToken: $(HelixApiAccessToken)
        HelixTargetQueues: $(Queue)
        HelixPreCommands: $(HelixPreCommand)
        HelixPostCommands: $(HelixPostCommand)
        Creator: $(Creator)
        WorkItemTimeout: 4:00 # 4 hours
        WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy
        CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions
        ProjectFile: ${{ parameters.projectFile }}
        osGroup: ${{ parameters.osGroup }}
    - task: PublishPipelineArtifact@1
      displayName: Publish Logs
      inputs:
        targetPath: $(Build.SourcesDirectory)/artifacts/log
        artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_${{ parameters.logicalMachine }}_${{ parameters.javascriptEngine }}_${{ parameters.pgoRunType }}_${{ parameters.physicalPromotionRunType }}_${{ parameters.r2rRunType }}_${{ parameters.experimentName }}'
      continueOnError: true
      condition: always()
